/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-07-25 13:47:51
 * @LastEditTime: 2021-07-25 18:31:13
 * @Description:  This files is for wdt ctrl function implementation
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 * 1.0   Wangxiaodong   2021/8/25   init
 */
#include <generic_timer.h>
#include <kernel.h>

#include "ft_types.h"
#include "ft_error_code.h"
#include "ft_debug.h"
#include "fwdt.h"
#include "fwdt_hw.h"
#include "parameters.h"

/* max timeout = 0xFFFFFFFF/ WDT_CLK = 89 */
#define FWDT_MAX_TIMEOUT 89

/**
 * @name: WdtSetTimeout
 * @msg: Set Timeout Value 
 * @return {u32} timeout set status, WDT_ERR_TIMEOUT or WDT_SUCCESS.
 * @param {WdtCtrl} *pctrl, pointer to a WdtCtrl structure that contains
  *                the configuration information for the specified wdt module.
 * @param {u32} timeout, represent in seconds, this parameter must be a number between 1 and 89.
 */
u32 FWdtSetTimeout(FWdtCtrl *pctrl, u32 timeout)
{
    if (timeout > FWDT_MAX_TIMEOUT)
    {
        FWDT_ERROR("timeout value is invalid, default 1s \n");
        return FWDT_ERR_TIMEOUT;
    }

    FWDT_SET_TIMEOUT(pctrl, timeout);
    
    pctrl->is_ready = FT_COMPONENT_IS_READY;

    return FWDT_SUCCESS;
}

/**
 * @name: WdtGetTimeleft
 * @msg: Get Timeout countdown, in seconds
 * @return {u32} Timeout countdown, in seconds
 * @param {WdtCtrl} *pctrl, pointer to a WdtCtrl structure that contains
  *                the configuration information for the specified wdt module.
 */
u32 FWdtGetTimeleft(FWdtCtrl *pctrl)
{
    u64 timeleft = 0;

    /* if the ws0 bit of register WCS is zero，indicates that there is one more timeout opportunity */
    if(!(FWDT_READ_WCS(pctrl) & FWDT_SBSA_GWDT_WCS_WS0))
        timeleft += FWDT_READ_WOR(pctrl);

    timeleft += FWDT_READ_WCV(pctrl) - GenericTimerRead();

    do_div(timeleft, WDT_CLK);

    return timeleft;
}

/**
 * @name: WdtRefresh
 * @msg: Refresh watchdog
 * @return {u32} status
 * @param {*} 
 */
u32 FWdtRefresh(FWdtCtrl *pctrl)
{
    FWDT_REFRESH(pctrl, FWDT_REFRESH_VALUE);
    return FWDT_SUCCESS;
}

/**
 * @name: WdtStart
 * @msg: Start watchdog
 * @return {u32} status
 * @param {*} 
 */
u32 FWdtStart(FWdtCtrl *pctrl)
{
    FWDT_START(pctrl, FWDT_SBSA_GWDT_WCS_EN);
    return FWDT_SUCCESS;
}

/**
 * @name: WdtStop
 * @msg: Stop watchdog
 * @return {u32} status
 * @param {WdtCtrl} *pctrl,  pointer to a WdtCtrl structure that contains
  *                the configuration information for the specified wdt module.
 */
u32 FWdtStop(FWdtCtrl *pctrl)
{
    FWDT_STOP(pctrl, FWDT_STOP_VALUE);
    return FWDT_SUCCESS;
}

/**
 * @name: FWdtReadWCVH
 * @msg:  Read wdt wcvh register value. wcvl and wclh register stores the comparison value of the watchdog count. 
 *          timeout value = comparison value - sys_cnt.
 * @return {void} 
 * @param {FWdtCtrl} *pctrl,  pointer to a WdtCtrl structure that contains
  *                the configuration information for the specified wdt module.
 */
u32 FWdtReadWCVH(FWdtCtrl *pctrl)
{
    return FWDT_READ_REG32(pctrl, FWDT_SBSA_GWDT_WCVH);
}

/**
 * @name: FWdtReadWCVL
 * @msg:  Read wdt wcvl register value. wcvl and wclh register stores the comparison value of the watchdog count. 
 *          timeout value = comparison value - sys_cnt.
 * @return {void} 
 * @param {FWdtCtrl} *pctrl,  pointer to a WdtCtrl structure that contains
  *                the configuration information for the specified wdt module.
 */
u32 FWdtReadWCVL(FWdtCtrl *pctrl)
{
    return FWDT_READ_REG32(pctrl, FWDT_SBSA_GWDT_WCVL);
}

/**
 * @name: FWdtReadWOR
 * @msg:  Read wdt wor register value. used to set timeout value, wor + sys_cnt = wcv.
 * @return {void} 
 * @param {FWdtCtrl} *pctrl,  pointer to a WdtCtrl structure that contains
  *                the configuration information for the specified wdt module.
 */
u32 FWdtReadWOR(FWdtCtrl *pctrl)
{
    return FWDT_READ_REG32(pctrl, FWDT_SBSA_GWDT_WOR);
}

/**
 * @name: FWdtReadWCS
 * @msg:  Read wdt wcs register value. wcs is control and state register. bit0 enable(1) or disable(0) wdt.
 * @return {void} 
 * @param {FWdtCtrl} *pctrl,  pointer to a WdtCtrl structure that contains
  *                the configuration information for the specified wdt module.
 */
u32 FWdtReadWCS(FWdtCtrl *pctrl)
{
    return FWDT_READ_REG32(pctrl, FWDT_SBSA_GWDT_WCS);
}
